﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MainPage.xaml.cs" company="Mar3ek">
//   This code is licensed under the Mozilla Public License 2.0.
//   You can find the full license text at the following address:
//   https://winkee.codeplex.com/license
// </copyright>
// <summary>
//   A page that displays a grouped collection of items.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace WinKee.Pages
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Input;

    using KeePassLib;
    using KeePassLib.Keys;
    using KeePassLib.Serialization;

    using Windows.ApplicationModel.Activation;
    using Windows.Phone.UI.Input;
    using Windows.Storage;
    using Windows.Storage.AccessCache;
    using Windows.Storage.Pickers;
    using Windows.Storage.Streams;
    using Windows.System;
    using Windows.UI.Core;
    using Windows.UI.Popups;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media.Imaging;
    using Windows.UI.Xaml.Navigation;

    using WinKee.Common;
    using WinKee.Models;

    using WinKeeLib.Keys;

    /// <summary>
    /// The login page.
    /// </summary>
    public sealed partial class MainPage : IFileOpenPickerContinuable, INotifyPropertyChanged
    {
        #region Fields

        /// <summary>
        /// Number of key transformation rounds to perform in the benchmark.
        /// </summary>
        private const long KeyBenchmarkRounds = 10000;

        /// <summary>
        /// The navigation helper.
        /// </summary>
        private readonly NavigationHelper navigationHelper;

        /// <summary>
        /// The display password.
        /// </summary>
        private bool displayPassword;

        /// <summary>
        /// The file name.
        /// </summary>
        private string fileName;

        /// <summary>
        /// The file path.
        /// </summary>
        private string filePath;

        /// <summary>
        /// The image source.
        /// </summary>
        private BitmapImage imageSource;

        /// <summary>
        /// The password.
        /// </summary>
        private string password;

        /// <summary>
        /// The key file name.
        /// </summary>
        private string keyfileName;

        /// <summary>
        /// The key file path.
        /// </summary>
        private string keyfilePath;

        /// <summary>
        /// The key file stream.
        /// </summary>
        private IRandomAccessStream keyfileStream;

        /// <summary>
        /// The DB file stream.
        /// </summary>
        private IRandomAccessStream fileStream;

        /// <summary>
        /// The cancellation source.
        /// </summary>
        private CancellationTokenSource cancellationSource;

        private bool isDecrypting;

        private Visibility isPickFileVisible = Visibility.Visible;

        private Visibility isAddKeyfileVisible = Visibility.Collapsed;

        private Visibility isRemoveKeyfileVisible = Visibility.Collapsed;

        private Visibility isUnlockVisible = Visibility.Collapsed;

        private Visibility isCancelVisible = Visibility.Collapsed;

        private long keyTransformationRounds;

        private double estimatedOpeningTime;

        private List<Tuple<string, string>> recentFiles;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="MainPage"/> class.
        /// </summary>
        public MainPage()
        {
            this.InitializeComponent();

            this.AddKeyfileCommand = new RelayCommand(AddKeyfileAction);
            this.SelectDatabaseCommand = new RelayCommand(SelectDatabaseAction);
            this.OpenCommand = new RelayCommand(this.OpenAction);
            this.RemoveKeyfileCommand = new RelayCommand(this.RemoveKeyfileAction);
            this.ShowAboutCommand = new RelayCommand(this.ShowAboutAction);
            this.CancelCommand = new RelayCommand(this.CancelAction);

            this.navigationHelper = new NavigationHelper(this);
            this.DataContext = this;
            this.Loaded += this.OnLoaded;
            HardwareButtons.BackPressed += this.HardwareButtonsOnBackPressed;

            if (ApplicationData.Current.LocalSettings.ReadSetting(Definitions.UseMRUSettingKey, false))
            {
                this.RecentFiles =
                StorageApplicationPermissions.MostRecentlyUsedList.Entries.Select(
                    e => new Tuple<string,string>(e.Token, e.Metadata)).ToList();
            }
            else
            {
                listView.Visibility = Visibility.Collapsed;
            }
        }

        public List<Tuple<string, string>> RecentFiles
        {
            get
            {
                return this.recentFiles;
            }

            private set
            {
                this.recentFiles = value;
                this.OnPropertyChanged();
            }
        }

        #endregion

        #region Public Events

        /// <summary>
        /// The property changed.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets a value indicating whether display password.
        /// </summary>
        public bool DisplayPassword
        {
            get
            {
                return this.displayPassword;
            }

            set
            {
                this.displayPassword = value;

                VisualStateManager.GoToState(this, value ? "FileOpenStateText" : "FileOpenStatePass", true);

                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets or sets the file stream.
        /// </summary>
        public IRandomAccessStream FileStream
        {
            get
            {
                return this.fileStream;
            }

            set
            {
                this.fileStream = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets or sets the image source.
        /// </summary>
        public BitmapImage ImageSource
        {
            get
            {
                return this.imageSource;
            }

            set
            {
                this.imageSource = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets the <see cref="NavigationHelper"/> associated with this <see cref="Page"/>.
        /// </summary>
        public NavigationHelper NavigationHelper
        {
            get
            {
                return this.navigationHelper;
            }
        }

        /// <summary>
        /// Gets or sets the password.
        /// </summary>
        public string Password
        {
            get
            {
                return this.password;
            }

            set
            {
                this.password = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets or sets the selected file name.
        /// </summary>
        public string SelectedFileName
        {
            get
            {
                return this.fileName;
            }

            set
            {
                this.fileName = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets or sets the selected file path.
        /// </summary>
        public string SelectedFilePath
        {
            get
            {
                return this.filePath;
            }

            set
            {
                this.filePath = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets the select database command.
        /// </summary>
        public ICommand SelectDatabaseCommand { get; private set; }

        /// <summary>
        /// Gets the add key file command.
        /// </summary>
        public ICommand AddKeyfileCommand { get; private set; }

        /// <summary>
        /// Gets the open command.
        /// </summary>
        public ICommand OpenCommand { get; private set; }

        /// <summary>
        /// Gets the remove key file command.
        /// </summary>
        public ICommand RemoveKeyfileCommand { get; private set; }

        /// <summary>
        /// Gets or sets the key file name.
        /// </summary>
        public string KeyfileName
        {
            get
            {
                return this.keyfileName;
            }

            set
            {
                this.keyfileName = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets or sets the key file path.
        /// </summary>
        public string KeyfilePath
        {
            get
            {
                return this.keyfilePath;
            }

            set
            {
                this.keyfilePath = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets or sets the key file stream.
        /// </summary>
        public IRandomAccessStream KeyfileStream
        {
            get
            {
                return this.keyfileStream;
            }

            set
            {
                this.keyfileStream = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// Gets the show about command.
        /// </summary>
        public ICommand ShowAboutCommand { get; private set; }

        /// <summary>
        /// Gets the cancel command.
        /// </summary>
        public ICommand CancelCommand { get; private set; }

        /// <summary>
        /// Gets or sets a value indicating whether is decrypting.
        /// </summary>
        public bool IsDecrypting
        {
            get
            {
                return this.isDecrypting;
            }

            set
            {
                this.isDecrypting = value;
                this.OnPropertyChanged();
            }
        }

        public Visibility IsPickFileVisible
        {
            get
            {
                return this.isPickFileVisible;
            }

            set
            {
                this.isPickFileVisible = value;
                this.OnPropertyChanged();
            }
        }

        public Visibility IsAddKeyfileVisible
        {
            get
            {
                return this.isAddKeyfileVisible;
            }

            set
            {
                this.isAddKeyfileVisible = value;
                this.OnPropertyChanged();
            }
        }

        public Visibility IsRemoveKeyfileVisible
        {
            get
            {
                return this.isRemoveKeyfileVisible;
            }

            set
            {
                this.isRemoveKeyfileVisible = value;
                this.OnPropertyChanged();
            }
        }

        public Visibility IsUnlockVisible
        {
            get
            {
                return this.isUnlockVisible;
            }

            set
            {
                this.isUnlockVisible = value;
                this.OnPropertyChanged();
            }
        }

        public Visibility IsCancelVisible
        {
            get
            {
                return this.isCancelVisible;
            }

            set
            {
                this.isCancelVisible = value;
                this.OnPropertyChanged();
            }
        }

        public long KeyTransformationRounds
        {
            get
            {
                return this.keyTransformationRounds;
            }

            set
            {
                this.keyTransformationRounds = value;
                this.OnPropertyChanged();
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The continue file open picker.
        /// </summary>
        /// <param name="args">
        /// The args.
        /// </param>
        public async void ContinueFileOpenPicker(FileOpenPickerContinuationEventArgs args)
        {
            if (args.Files.Count <= 0)
            {
                return;
            }

            var operation = args.ContinuationData["Operation"] as string;

            switch (operation)
            {
                case "SelectDB":
                    {
                        var file = args.Files[0];

                        // adds the file to the most recently used list
                        await this.ProcessDatabaseSelection(file);
                    }

                    break;
                case "AddKeyfiles":
                    this.KeyfileName = args.Files[0].Name;
                    this.KeyfilePath = args.Files[0].Path;
                    this.KeyfileStream = await args.Files[0].OpenAsync(FileAccessMode.Read);
                    this.IsRemoveKeyfileVisible = Visibility.Visible;
                    break;
            }
        }

        private async Task ProcessDatabaseSelection(StorageFile file)
        {
            if (file == null)
            {
                return;
            }

            VisualStateManager.GoToState(this, "FileOpenStatePass", true);

            if (ApplicationData.Current.LocalSettings.ReadSetting(Definitions.UseMRUSettingKey, false))
            {
                StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Name);
            }

            this.IsAddKeyfileVisible = Visibility.Visible;

            this.SelectedFilePath = file.Path;
            this.SelectedFileName = file.Name;

            if (this.FileStream != null)
            {
                this.FileStream.Dispose();
                this.FileStream = null;
            }

            this.FileStream = await file.OpenAsync(FileAccessMode.Read);
            this.EstimatedOpeningTime = 0;

            this.OpenDatabaseStream();
        }

        private void OpenDatabaseStream()
        {
            // calculate key transformation benchmark
            var sw = new Stopwatch();
            const int AverageRounds = 10;
            for (var i = 0; i < AverageRounds; i++)
            {
                sw.Start();
                CompositeKey.TransformKeyManaged(new byte[32], new byte[32], KeyBenchmarkRounds, CancellationToken.None);
                sw.Stop();
            }

            try
            {
                var db = new PwDatabase();
                db.ReadHeader(this.FileStream.GetInputStreamAt(0).AsStreamForRead());

                this.KeyTransformationRounds = (long)db.KeyEncryptionRounds;
                var seconds =
                    new TimeSpan(
                        (this.KeyTransformationRounds / KeyBenchmarkRounds) * (sw.ElapsedTicks / AverageRounds))
                        .TotalSeconds;

                this.EstimatedOpeningTime = Math.Round(seconds + (seconds / 10), 2);               
            }
            catch (Exception ex)
            {
                Dispatcher.RunAsync(
                    CoreDispatcherPriority.Normal,
                    async () =>
                        {
                            await HandleException(ex);
                        });
            }
            finally
            {
                if (this.DisplayPassword)
                {
                    this.PasswordTextBox.Focus(FocusState.Keyboard);
                }
                else
                {
                    this.PasswordBox.Focus(FocusState.Keyboard);
                }

                this.IsUnlockVisible = Visibility.Visible;
            }
        }

        public double EstimatedOpeningTime
        {
            get
            {
                return this.estimatedOpeningTime;
            }

            set
            {
                this.estimatedOpeningTime = value;
                this.OnPropertyChanged();
            }
        }

        public ICommand AddDBExtensionCommand { get; private set; }

        public ICommand AddKFExtensionCommand { get; private set; }

        #endregion

        #region Methods

        /// <summary>
        /// The on navigated from.
        /// </summary>
        /// <param name="e">
        /// The e.
        /// </param>
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            this.navigationHelper.OnNavigatedFrom(e);
        }

        /// <summary>
        /// The methods provided in this section are simply used to allow
        /// NavigationHelper to respond to the page's navigation methods.
        /// <para>
        /// Page specific logic should be placed in event handlers for the
        /// <see cref="NavigationHelper.LoadState"/>
        /// and <see cref="NavigationHelper.SaveState"/>.
        /// The navigation parameter is available in the LoadState method
        /// in addition to page state preserved during an earlier session.
        /// </para>
        /// </summary>
        /// <param name="e">
        /// Event data that describes how this page was reached.
        /// </param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            this.IsPickFileVisible = Visibility.Visible;
            
            var stringContent = e.Parameter as string;

            if (!string.IsNullOrEmpty(stringContent))
            {
                var split = stringContent.Split('|');

                this.IsAddKeyfileVisible = Visibility.Visible;
                this.IsUnlockVisible = Visibility.Visible;

                var file =
                    ApplicationData.Current.TemporaryFolder.CreateFileAsync(
                        "temporary.kdbx",
                        CreationCollisionOption.ReplaceExisting).AsTask().Result;

                FileIO.WriteBytesAsync(file, Convert.FromBase64String(split[1])).AsTask().Wait();

                this.SelectedFilePath = "<temporary path>";
                this.SelectedFileName = split[0];
                this.FileStream = file.OpenAsync(FileAccessMode.Read).AsTask().Result;

                this.DisplayPassword = false;
                this.Password = string.Empty;
                this.OpenDatabaseStream();
            }
            else
            {
                this.FileStream = null;
                this.IsAddKeyfileVisible = Visibility.Collapsed;
                this.IsUnlockVisible = Visibility.Collapsed;
                this.DisplayPassword = false;
                this.Password = string.Empty;
            }

            this.IsRemoveKeyfileVisible = Visibility.Collapsed;
            this.IsCancelVisible = Visibility.Collapsed;

            this.Frame.BackStack.Clear();
            this.navigationHelper.OnNavigatedTo(e);
        }

        /// <summary>
        /// Selects a database file.
        /// </summary>
        private static void SelectDatabaseAction()
        {
            var picker = new FileOpenPicker();
            picker.FileTypeFilter.Add("*");

            try
            {
                picker.ContinuationData["Operation"] = "SelectDB";
                ((App)Application.Current).ContinuationManager.MarkAsStale();
                picker.PickSingleFileAndContinue();
            }
            catch (Exception)
            {
                var md =
                    new MessageDialog("Exception while trying to open the file picker. Please restart the application.")
                    {
                        Title
                            =
                            "File picker exception"
                    };
                md.Commands.Add(new UICommand("OK"));

                md.ShowAsync().AsTask().ContinueWith(result => Application.Current.Exit());
            }
        }

        /// <summary>
        /// Adds a key file.
        /// </summary>
        private static void AddKeyfileAction()
        {
           

            var picker = new FileOpenPicker();

            picker.FileTypeFilter.Add("*");

            try
            {
                picker.ContinuationData["Operation"] = "AddKeyfiles";
                ((App)Application.Current).ContinuationManager.MarkAsStale();
                picker.PickSingleFileAndContinue();
            }
            catch (Exception)
            {
                var md =
                    new MessageDialog("Exception while trying to open the file picker. Please restart the application.")
                    {
                        Title
                            =
                            "File picker exception"
                    };
                md.Commands.Add(new UICommand("OK"));

                md.ShowAsync().AsTask().ContinueWith(result => Application.Current.Exit());
            }
        }

        private void HardwareButtonsOnBackPressed(object sender, BackPressedEventArgs backPressedEventArgs)
        {
            backPressedEventArgs.Handled = true;
            Application.Current.Exit();
        }

        /// <summary>
        /// The on loaded.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="routedEventArgs">
        /// The routed event args.
        /// </param>
        private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            if (this.FileStream != null)
            {
                VisualStateManager.GoToState(this, "FileOpenStatePass", true);
                this.PasswordBox.Focus(FocusState.Keyboard);
            }
            else
            {
                VisualStateManager.GoToState(this, "PickerState", true);
            }
        }

        /// <summary>
        /// The on property changed.
        /// </summary>
        /// <param name="propertyName">
        /// The property name.
        /// </param>
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// The password box_ on key down.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void PasswordBox_OnKeyDown(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key == VirtualKey.Enter)
            {
                this.OpenCommand.Execute(null);
            }
        }

        /// <summary>
        /// Opens a database file.
        /// </summary>
        private async void OpenAction()
        {
            if (this.FileStream == null)
            {
                var md = new MessageDialog("You must pick a file to open first.", "Pick a file");
                md.Commands.Add(new UICommand("OK"));
                await md.ShowAsync();
                return;
            }

            if (string.IsNullOrEmpty(this.PasswordBox.Password) && this.KeyfileStream == null)
            {
                var md = new MessageDialog("You must specify a password or choose a key file.") { Title = "Password required" };
                md.Commands.Add(new UICommand("OK"));
                await md.ShowAsync();
                return;
            }

            VisualStateManager.GoToState(this, "DecryptingState", true);
            this.IsPickFileVisible = Visibility.Collapsed;
            this.IsAddKeyfileVisible = Visibility.Collapsed;
            this.IsUnlockVisible = Visibility.Collapsed;
            this.IsRemoveKeyfileVisible = Visibility.Collapsed;
            this.IsCancelVisible = Visibility.Visible;

            this.cancellationSource = new CancellationTokenSource();

            var statusBar = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
            statusBar.ProgressIndicator.ProgressValue = null;
            await statusBar.ShowAsync();         
            await statusBar.ProgressIndicator.ShowAsync();

            var pass = this.DisplayPassword ? this.PasswordTextBox.Text : this.PasswordBox.Password;

            PasswordGroup rootGroup = null;

            Exception thrownException = null;
            this.IsDecrypting = true;

            await Task.Run(
                () =>
                    {
                        try
                        {
                            var key = new CompositeKey();

                            if (!string.IsNullOrEmpty(pass))
                            {
                                key.AddUserKey(new KcpPassword(pass));
                            }

                            if (this.KeyfileStream != null)
                            {
                                this.KeyfileStream.Seek(0);
                                key.AddUserKey(new KcpKeyFile(this.KeyfileStream.AsStreamForRead()));
                            }

                            var db = new PwDatabase();

                            db.Open(
                                this.FileStream.GetInputStreamAt(0).AsStreamForRead(),
                                key,
                                null,
                                this.cancellationSource.Token);

                            Debug.Assert(db != null, "db != null");

                            rootGroup = ParseGroup(db.RootGroup, db.RecycleBinEnabled, db.RecycleBinUuid);
                        }
                        catch (OperationCanceledException)
                        {
                        }
                        catch (Exception ex)
                        {
                            thrownException = ex;
                        }
                    });

            this.DisplayPasswordCheckBox.IsChecked = false;
            VisualStateManager.GoToState(this, "FileOpenStatePass", true);
            await statusBar.HideAsync();
            await statusBar.ProgressIndicator.HideAsync();

            this.IsDecrypting = false;

            this.IsPickFileVisible = Visibility.Visible;
            this.IsAddKeyfileVisible = Visibility.Visible;
            this.IsUnlockVisible = Visibility.Visible;
            this.IsRemoveKeyfileVisible = this.keyfileStream != null ? Visibility.Visible : Visibility.Collapsed;
            this.IsCancelVisible = Visibility.Collapsed;

            if (thrownException != null)
            {
                await HandleException(thrownException);
                return;
            }

            if (this.cancellationSource.IsCancellationRequested)
            {
                // operation was cancelled
                return;
            }

            HardwareButtons.BackPressed -= this.HardwareButtonsOnBackPressed;
            this.FileStream.Dispose();
            this.FileStream = null;
            this.Frame.Navigate(typeof(DatabasePage), rootGroup.Serialize());
        }

        private static PasswordGroup ParseGroup(PwGroup group, bool recycleBinEnabled, PwUuid recycleBinUuid)
        {
            var result = new PasswordGroup(group)
                             {
                                 Groups =
                                     @group.Groups.Where(
                                         g => !recycleBinEnabled || !g.Uuid.Equals(recycleBinUuid))
                                     .Select(g => ParseGroup(g, recycleBinEnabled, recycleBinUuid))
                                     .OrderBy(g => g.GroupName)
                                     .ToList()
                             };

            return result;
        }

        private static async Task HandleException(Exception thrownException)
        {
            var message =
                "An exception occured while opening the database file. If the issue persists, report this issue at http://winkee.codeplex.com or by pressing the Report button below.";
            var title = "Exception";

            if (thrownException is FormatException)
            {
                if (thrownException.Message.Contains("The file signature is invalid."))
                {
                    message =
                        "This file does not appear to be a KeePass database. Please make sure you are opening a valid KeePass 2.x database and try again.";
                }
                else
                {
                    message =
                        "The database file seems to be corrupted. Make sure the specified file is a valid KeePass database. If the issue persists, report this issue at http://winkee.codeplex.com or by pressing the Report button below.";
                }
                
                title = "Unable to decrypt";
            }
            else if (thrownException is InvalidCompositeKeyException)
            {
                message =
                    "The password and/or key file do not match the database. Make sure you are using the right credentials for you file. If the issue persists, report this issue at http://winkee.codeplex.com or by pressing the Report button below.";
                title = "Unable to decrypt";
            }
            else if (thrownException is OldFormatException)
            {
                message =
                    "You are attempting to decrypt a KeePass 1.x database. WinKee only supports KeePass 2.x databases. Upgrade your database and try again.";
                title = "Old database format";
            }

            var md = new MessageDialog(message, title);
            md.Commands.Add(new UICommand("OK"));
            md.Commands.Add(new UICommand("Report", async command => await ReportException(thrownException)));

            await md.ShowAsync();
        }

        private async static Task ReportException(Exception ex)
        {
            await ErrorReporter.ReportException(ex);
        }

        /// <summary>
        /// Removes a key file.
        /// </summary>
        private void RemoveKeyfileAction()
        {
            this.KeyfileStream = null;
            this.KeyfileName = string.Empty;
            this.KeyfilePath = string.Empty;
            this.IsRemoveKeyfileVisible = Visibility.Collapsed;
        }

        /// <summary>
        /// Shows the about page.
        /// </summary>
        private void ShowAboutAction()
        {
            this.Frame.Navigate(typeof(AboutPage));
        }

        private void CancelAction()
        {
            if (this.cancellationSource != null)
            {
                this.cancellationSource.Cancel();
            }
        }

        #endregion

        private async void RecentFiles_OnItemClick(object sender, ItemClickEventArgs e)
        {
            var item = e.ClickedItem as Tuple<string, string>;

            if (item == null)
            {
                return;
            }

            var file = await StorageApplicationPermissions.MostRecentlyUsedList.GetFileAsync(item.Item1);
            await this.ProcessDatabaseSelection(file);
        }
    }
}